﻿// ===============================================================================
// Extensions.cs
// EOS Framework
// ===============================================================================
// Copyright (c) EOS Development Group. All rights reserved.
// ===============================================================================

namespace EOS.Framework.Tools
{
    using System;
    using System.Collections;
    using System.Collections.Generic;

    /// <summary>
    /// A collection of simple helper extension methods.
    /// </summary>
    public static class Extensions
    {
        public static bool IsBetween<TValue>(this TValue value, TValue low, TValue high) where TValue : IComparable
        {
            return (Comparer<TValue>.Default.Compare(low, value) <= 0
                && Comparer<TValue>.Default.Compare(high, value) >= 0);
        }

        /// <summary>
        /// Checks if the two passed lists are equal. They are equal if they contains
        /// the same number of items and all items are equal in the same order.
        /// </summary>
        /// <typeparam name="TItem">The type of the items in the lists.</typeparam>
        /// <param name="source">The source list for comparison.</param>
        /// <param name="target">The target list, which will be compared with the source list.</param>
        /// <returns>
        /// 	<c>true</c> if the specified source is equal to the target; otherwise, <c>false</c>.
        /// </returns>
        public static bool IsEqual<TItem>(this IList<TItem> source,
            IList<TItem> target)
        {
            if (target == null && source == null)
            {
                return true;
            }
            else if (target == null || source == null)
            {
                return false;
            }

            bool result = true;

            if (source.Count == target.Count)
            {
                for (int i = 0; i < source.Count && result == true; i++)
                {
                    if (!Object.Equals(source[i], target[i]))
                    {
                        result = false;
                    }
                }
            }
            else
            {
                result = false;
            }

            return result;
        }


        public static bool IsEqual<TKey, TValue>(this IDictionary<TKey, TValue> source,
            IDictionary<TKey, TValue> target)
        {
            if (target == null && source == null)
            {
                return true;
            }
            else if (target == null || source == null)
            {
                return false;
            }

            bool result = true;

            if (source.Count == target.Count)
            {
                foreach (KeyValuePair<TKey, TValue> kvPair in source)
                {
                    if (!target.ContainsKey(kvPair.Key) || !Object.Equals(target[kvPair.Key], kvPair.Value))
                    {
                        result = false;
                    }
                }
            }
            else
            {
                result = false;
            }

            return result;
        }

        /// <summary>
        /// Checks if the two passed lists are equal. They are equal if they contains
        /// the same number of items and all items are equal. The items in the two lists
        /// must not be in the same order.
        /// </summary>
        /// <typeparam name="TItem">The type of the items in the lists.</typeparam>
        /// <param name="source">The source list for comparison.</param>
        /// <param name="target">The target list, which will be compared with the source list.</param>
        /// <returns>
        /// 	<c>true</c> if the specified source is equal to the target; otherwise, <c>false</c>.
        /// </returns>
        public static bool IsEqualUnsorted<TItem>(this IList<TItem> source,
            IList<TItem> target)
        {
            if (target == null && source == null)
            {
                return true;
            }
            else if (target == null || source == null)
            {
                return false;
            }

            bool result = true;

            if (source.Count == target.Count)
            {
                IList<TItem> temp = new List<TItem>(target);

                for (int i = 0; i < source.Count && result; i++)
                {
                    bool found = false;
                    for (int j = 0; j < temp.Count; j++)
                    {
                        if (Object.Equals(source[i], temp[j]))
                        {
                            temp.RemoveAt(j);
                            found = true;
                            break;
                        }
                    }

                    found = result;
                }
            }
            else
            {
                result = false;
            }

            return result;
        }

        /// <summary>
        /// Creates a hash code for a list be making a bitwise or for each hash code
        /// of each item.
        /// </summary>
        /// <typeparam name="TItem">The type of the list items.</typeparam>
        /// <param name="list">The list where the hashCode should be created from.</param>
        /// <returns>The hashCode of the list.</returns>
        public static int CreateHashCode(this IList list)
        {
            int hashCode = list.GetHashCode();

            foreach (object value in list)
            {
                hashCode ^= value.GetHashCode();
            }

            return hashCode;
        }

        /// <summary>
        /// Creates a hash code for a dictionary be making a bitwise or for each hash code
        /// of each item.
        /// </summary>
        /// <typeparam name="TItem">The type of the list items.</typeparam>
        /// <param name="list">The list where the hashCode should be created from.</param>
        /// <returns>The hashCode of the list.</returns>
        public static int CreateHashCode(this IDictionary dictionary)
        {
            int hashCode = dictionary.GetHashCode();

            foreach (object value in dictionary.Values)
            {
                hashCode ^= value.GetHashCode();
            }

            foreach (object key in dictionary.Keys)
            {
                hashCode ^= key.GetHashCode();
            }

            return hashCode;
        }

        public static TValue RemainBetween<TValue>(this TValue value, TValue low, TValue high) where TValue : IComparable
        {
            TValue result = value;

            if (Comparer<TValue>.Default.Compare(high, low) < 0)
            {
                high = low;
            }

            if (Comparer<TValue>.Default.Compare(value, low) <= 0)
            {
                result = low;
            }

            if (Comparer<TValue>.Default.Compare(value, high) >= 0)
            {
                result = high;
            }

            return result;
        }
    }
}
